﻿using System;
using System.Linq;
using System.Xml.Linq;
using Loki.Utils;

namespace Luna.Connectors.ZohoCRM
{
    public class ZohoResponse : LokiObject
    {
        private XElement _ResultNode;

        internal ZohoResponse(string P_Module, string P_Method, string P_ResponseContent)
        {
            if (P_Module == null)
            {
                throw BuildError<ArgumentNullException>(Resources.Errors.ASSERT_MODULE_REQUIRED);
            }

            if (P_Method == null)
            {
                throw BuildError<ArgumentNullException>(Resources.Errors.ASSERT_METHOD_REQUIRED);
            }

            Method = P_Method;
            Module = P_Module;
            ResponseContent = P_ResponseContent;

            var L_LoadedDocument = XDocument.Parse(P_ResponseContent);
            LoadFromXml(L_LoadedDocument.Root);
        }

        public string Module { get; private set; }

        public string Method { get; private set; }

        public bool IsError { get; private set; }

        public string Message { get; private set; }

        public string Code { get; private set; }

        public bool NoData { get; private set; }

        internal string ResponseContent { get; private set; }

        public ZohoResponseException Error
        {
            get { return !IsError ? null : new ZohoResponseException(this); }
        }

        public void ThrowIfError()
        {
            if (IsError)
            {
                throw BuildErrorFormat<ZohoResponseException>(Resources.Errors.ZOHO_ERROR, Error, Error.ErrorCode);
            }
        }

        internal virtual void LoadFromXml(XElement P_Parent)
        {
            if (P_Parent.Name != SerializerParams.ELEMENT_RESPONSE)
            {
                throw BuildError<FormatException>(Resources.Errors.INVALID_FORMAT_RESPONSE);
            }

            var L_FirstChild = P_Parent.Elements().First();
            if (L_FirstChild.Name == SerializerParams.ELEMENT_ERROR)
            {
                IsError = true;
                var L_Code = L_FirstChild.Descendants(SerializerParams.ELEMENT_ERROR_CODE).FirstOrDefault();
                var L_Message = L_FirstChild.Descendants(SerializerParams.ELEMENT_ERROR_MESSAGE).FirstOrDefault();
                if (L_Code != null)
                {
                    Code = L_Code.Value;
                }

                if (L_Message != null)
                {
                    Message = L_Message.Value;
                }
            }
            else if (L_FirstChild.Name == SerializerParams.ELEMENT_RESULT)
            {
                LoadResultFromXml(L_FirstChild);
            }
            else if (L_FirstChild.Name == SerializerParams.ELEMENT_NODATA)
            {
                var L_Code = L_FirstChild.Descendants(SerializerParams.ELEMENT_ERROR_CODE).FirstOrDefault();
                var L_Message = L_FirstChild.Descendants(SerializerParams.ELEMENT_ERROR_MESSAGE).FirstOrDefault();
                if (L_Code != null)
                {
                    Code = L_Code.Value;
                }

                if (L_Message != null)
                {
                    Message = L_Message.Value;
                }

                IsError = Code != null || Message != null;
                NoData = true;
            }
        }

        internal virtual void LoadResultFromXml(XElement P_ResultElement)
        {
            if (P_ResultElement.Descendants(SerializerParams.ELEMENT_ERROR_CODE).Any())
            {
                var L_Code = P_ResultElement.Descendants(SerializerParams.ELEMENT_ERROR_CODE).First();
                var L_Message = P_ResultElement.Descendants(SerializerParams.ELEMENT_ERROR_MESSAGE).First();
                if (L_Code != null)
                {
                    Code = L_Code.Value;
                }

                if (L_Message != null)
                {
                    Message = L_Message.Value;
                }

                IsError = Code != null || Message != null;
            }
            else
            {
                _ResultNode = P_ResultElement;
            }
        }

        internal ZohoEntityCollection<T> LoadCollectionFromResul<T>() where T : ZohoEntity
        {
            var L_Collection = new ZohoEntityCollection<T>(true);
            if (!NoData)
            {
                var L_FirstNode = _ResultNode.Elements().First();
                L_Collection.LoadFromXml(L_FirstNode);
            }

            return L_Collection;
        }
    }
}